package com.lyd.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Author:lyd 实现动态代理需要解决的问题：
 * 1、如何根据加载到内存中的被代理类，动态的创建一个代理类及其对象
 * 2、通过代理类的对象调用方法时，如何动态的调用被代理类中的同名方法
 **/
public class ProxyTest {
    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();
        //proxyInstance: 代理类的对象
        Human proxyInstance1 = (Human) ProxyFactory.getProxyInstance(superMan);
        proxyInstance1.eat();
        System.out.println(proxyInstance1.getBelief());

        NikeClothProxy nike = new NikeClothProxy();
        ClothFactory proxyInstance2 = (ClothFactory) ProxyFactory.getProxyInstance(nike);
        proxyInstance2.produceCloth();
    }


}

interface Human {
    String getBelief();

    void eat();
}

//被代理类
class SuperMan implements Human {
    @Override
    public String getBelief() {
        return "I CAN SAVE WORLD!";
    }

    @Override
    public void eat() {
        System.out.println("我爱吃骚烤");
    }
}

class ProxyFactory {
    public static Object getProxyInstance(Object obj) {
//        MyInvocationHandler handler = new MyInvocationHandler();
//        handler.bind(obj);
        // 根据被代理类，动态的创建一个代理类及其对象
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
                (proxy, method, args) -> method.invoke(obj, args));
    }
}

class MyInvocationHandler implements InvocationHandler {
    //obj:被代理类对象
    private Object obj;

    public void bind(Object obj) {
        this.obj = obj;
    }

    //当我们通过代理类的对象，调用方法时，就会调用如下的方法：invoke（）
    //将被代理类要执行的方法的功能就声明在invoke（）
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(obj, args);
    }
}


